Fire watches once immediately upon registration.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 19 Sep 2005 14:47:56 +0000 (14:47 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 19 Sep 2005 14:47:56 +0000 (14:47 +0000)
It matches the model of programming used to avoid races with watches,
and also makes re-establishing watches on daemon restart easier.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
tools/xenstore/testsuite/07watch.test
tools/xenstore/testsuite/14complexperms.test
tools/xenstore/xenstored_watch.c
tools/xenstore/xs_test.c

index c081aa8240ce0b5f75831a9038804c169963f6f2..e884a1a2135678b006152653416aef15eae728ea 100644 (file)
@@ -228,6 +228,7 @@ static int blkback_probe(struct xenbus_device *dev,
        be->dev = dev;
        be->backend_watch.node = dev->nodename;
        be->backend_watch.callback = backend_changed;
+       /* Will implicitly call backend_changed once. */
        err = register_xenbus_watch(&be->backend_watch);
        if (err) {
                be->backend_watch.node = NULL;
@@ -249,8 +250,6 @@ static int blkback_probe(struct xenbus_device *dev,
        }
 
        dev->data = be;
-
-       backend_changed(&be->backend_watch, dev->nodename);
        return 0;
 
  free_be:
index 06d07cacf1cacd731ac71963d4d821faf62b5f55..771ff28eaa6212000a0aff75fa46aca1cd3b989d 100644 (file)
@@ -172,6 +172,7 @@ static int blkback_probe(struct xenbus_device *dev,
        be->dev = dev;
        be->backend_watch.node = dev->nodename;
        be->backend_watch.callback = backend_changed;
+       /* Registration implicitly fires backend_changed once */
        err = register_xenbus_watch(&be->backend_watch);
        if (err) {
                be->backend_watch.node = NULL;
@@ -193,8 +194,6 @@ static int blkback_probe(struct xenbus_device *dev,
        }
 
        dev->data = be;
-
-       backend_changed(&be->backend_watch, dev->nodename);
        return 0;
 
  free_be:
index d5a41728f7684f937bf12a840c05ad9220463534..1e1d27ecaa7e956a1f8956dab86feacec429951a 100644 (file)
@@ -242,6 +242,7 @@ static int netback_probe(struct xenbus_device *dev,
        be->dev = dev;
        be->backend_watch.node = dev->nodename;
        be->backend_watch.callback = backend_changed;
+       /* Registration implicitly calls backend_changed. */
        err = register_xenbus_watch(&be->backend_watch);
        if (err) {
                be->backend_watch.node = NULL;
@@ -263,8 +264,6 @@ static int netback_probe(struct xenbus_device *dev,
        }
 
        dev->data = be;
-
-       backend_changed(&be->backend_watch, dev->nodename);
        return 0;
 
  free_be:
index bc6fa05f01ede29318670f05bb80a8b3d74fb6d4..7f7d990ef2b808e62b3bb044c76ba5c9563ed5ae 100644 (file)
@@ -1284,10 +1284,6 @@ static int netfront_probe(struct xenbus_device *dev,
                return err;
        }
 
-
-       /* Call once in case entries already there. */
-       watch_for_status(&info->watch, info->watch.node);
-
        return 0;
 }
 
index 4e2a11f8380d6fb7506507dc892c9de90cfae624..59237b511b3d6c5df4e25262fd53ece75e65ffba 100644 (file)
@@ -213,6 +213,7 @@ static int tpmback_probe(struct xenbus_device *dev,
 
        be->dev = dev;
        be->backend_watch.node     = dev->nodename;
+       /* Implicitly calls backend_changed() once. */
        be->backend_watch.callback = backend_changed;
        be->instance = -1;
        err = register_xenbus_watch(&be->backend_watch);
@@ -236,8 +237,6 @@ static int tpmback_probe(struct xenbus_device *dev,
        }
 
        dev->data = be;
-
-       backend_changed(&be->backend_watch, dev->nodename);
        return err;
 
 free_be:
index 9df476781f9fbcaf662e35b33c13c998742e9ebc..ae94b3bbef2fadad414001e54d2d760c1ee6c424 100644 (file)
@@ -411,7 +411,6 @@ static int tpmfront_probe(struct xenbus_device *dev,
                return err;
        }
 
-       watch_for_status(&info->watch, info->watch.node);
        return 0;
 }
 
index 5ce41aa80bf165e9977a155a66e638d301891499..5ae025765e8a1294f9cf0f3b80400617910a3ea4 100644 (file)
@@ -168,10 +168,12 @@ expect 1: waitwatch failed: Connection timed out
 # Watch event must have happened before we registered interest.
 1 watch / token
 2 write /test/subnode contents2
-1 watch / token2 0
+1 watchnoack / token2 0
 expect 1:/test/subnode:token
 1 waitwatch
 1 ackwatch token
+expect 1:/:token2
+1 waitwatch
 expect 1: waitwatch failed: Connection timed out
 1 waitwatch
 1 close
index dc4b0cdbb691a9d221934286171c4eb08dc8d47d..9ac47a70b890ffad21864a1f2554702ebbfa265d 100644 (file)
@@ -23,7 +23,8 @@ expect *Permission denied
 getperm /dir/file 
 expect *Permission denied
 setperm /dir/file 0 NONE 
-watch /dir/file token 
+# We get no watch event when there's no permission.  It's a corner case.
+watchnoack /dir/file token 
 1 write /dir/file contents
 1 rm /dir/file
 expect waitwatch failed: Connection timed out
@@ -63,7 +64,7 @@ expect *Permission denied
 getperm /dir/file 
 expect *Permission denied
 setperm /dir/file 0 NONE 
-watch /dir/file token 
+watchnoack /dir/file token 
 1 write /dir/file contents
 1 rm /dir/file
 expect waitwatch failed: Connection timed out
index a543f8a4952e9a5e381b788348c5bdd4402baea7..74dd773694a95ac5f7627bd87308b9d9d0df275b 100644 (file)
@@ -236,6 +236,9 @@ void do_watch(struct connection *conn, struct buffered_data *in)
        trace_create(watch, "watch");
        talloc_set_destructor(watch, destroy_watch);
        send_ack(conn, XS_WATCH);
+
+       /* We fire once up front: simplifies clients and restart. */
+       add_event(conn, watch, watch->node);
 }
 
 void do_watch_ack(struct connection *conn, const char *token)
index 3d90632e2450e7f1a918bb870fe8bc32eccae191..85d3d25dde361a69db8298defcd08ae9ac2995b6 100644 (file)
@@ -200,6 +200,7 @@ static void __attribute__((noreturn)) usage(void)
             "  setperm <path> <id> <flags> ...\n"
             "  shutdown\n"
             "  watch <path> <token>\n"
+            "  watchnoack <path> <token>\n"
             "  waitwatch\n"
             "  ackwatch <token>\n"
             "  unwatch <path> <token>\n"
@@ -480,10 +481,20 @@ static void do_shutdown(unsigned int handle)
                failed(handle);
 }
 
-static void do_watch(unsigned int handle, const char *node, const char *token)
+static void do_watch(unsigned int handle, const char *node, const char *token,
+                    bool swallow_event)
 {
        if (!xs_watch(handles[handle], node, token))
                failed(handle);
+
+       /* Convenient for testing... */
+       if (swallow_event) {
+               char **vec = xs_read_watch(handles[handle]);
+               if (!vec || !streq(vec[0], node) || !streq(vec[1], token))
+                       failed(handle);
+               if (!xs_acknowledge_watch(handles[handle], token))
+                       failed(handle);
+       }
 }
 
 static void set_timeout(void)
@@ -767,7 +778,9 @@ static void do_command(unsigned int default_handle, char *line)
        else if (streq(command, "shutdown"))
                do_shutdown(handle);
        else if (streq(command, "watch"))
-               do_watch(handle, arg(line, 1), arg(line, 2));
+               do_watch(handle, arg(line, 1), arg(line, 2), true);
+       else if (streq(command, "watchnoack"))
+               do_watch(handle, arg(line, 1), arg(line, 2), false);
        else if (streq(command, "waitwatch"))
                do_waitwatch(handle);
        else if (streq(command, "ackwatch"))